package distributed.controller;

import java.sql.Date;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import distributed.entity.Edge;
import distributed.entity.Event;
import distributed.entity.EventModel;

import server.ClientState;
import xml.Message;

/**
 * Controller to handle an admin wishing to force the closure of open events
 * @author Sam Jaffe
 *
 */
public class ForceCloseController implements IProtocolController{

	/** Processes a message from a client */
	public Message process(ClientState state, Message request) {
		String xmlString;
		//get the request Attributes
		NamedNodeMap map = request.contents.getFirstChild().getAttributes();
		Node daysNode = map.getNamedItem("daysOld"); //Get the age node
		Node idNode = map.getNamedItem("id");// and the id node

		String key = map.getNamedItem("key").getNodeValue(); //And the session key
		int affected = 0;
		//If its a bad key, throw him out.
		if (!key.equals(state.getData())) {
			xmlString = Message.responseHeader(request.id(), "Invalid Authentication Key") +
			"<forceResponse numberAffected='" + affected + "'/></response>";
			return new Message(xmlString);
		}
		//Else, if the id node isn't these
		if (idNode == null) {
			if (daysNode == null) //If the age node doesn't either, there's not enough data
				xmlString = Message.responseHeader(request.id(), "Insufficent Data");
			else { //Else start building the message and closing events
				xmlString = Message.responseHeader(request.id());
				EventModel em = EventModel.getInstance();
				Date today = new Date(System.currentTimeMillis()
						-(Long.decode(daysNode.getNodeValue())*86400000L)); //Use the right age
				DataBaseController dbc = DataBaseController.getInstance();

				for (String id : em.getEventIDs()) { //Iterate through all the ids
					Event e = em.getEvent(id);
					if (e.getCreationDate().before(today)) {
						affected++;
						int i = 0;
						while (!e.done() && i<=64) {
							e.addEdge(new Edge(0, 10000+10*i));
							i++;
						}
						try {
							dbc.updateEvent(e, id);
						} catch (Exception e1) {}
							
					}
				}

				try {
					for (String id : dbc.getIdsOfOldEvents(today)) {
						Event e = dbc.retrieveEvent(id);
						if (e.getCreationDate().before(today)) {
							affected++;
							int i = 0;
							while (!e.done() && i<=64) {
								e.addEdge(new Edge(0, 10000+10*i));
								i++;
							}
							dbc.updateEvent(e, id);
						}
					}
				} catch (Exception e) {e.printStackTrace();}
			}
		}
		else { // If we had the id
			Event e = EventModel.getInstance().getEvent(idNode.getNodeValue());
			if (e != null) { // Make sure it exists
				xmlString = Message.responseHeader(request.id());
				affected++; //Close it
				e.close();
			}
			else
				xmlString = Message.responseHeader(request.id(), "This event does not exist");
		}
		//Return the response
		xmlString += "<forceResponse numberAffected='" + affected
				+ "'/></response>";

		return new Message(xmlString);
	}

	/**
	 * @return ForceCloseController
	 */
	public IProtocolController newCopy() {
		return new ForceCloseController();
	}

}
